package com.feemanage.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.common.api.ApprovalApi;
import com.common.core.domain.entity.SysUser;
import com.common.core.page.PageDomain;
import com.common.utils.CurrentRoleUtils;
import com.common.utils.SecurityUtils;
import com.common.utils.bean.BizProcessMessages;
import com.common.utils.sql.SqlUtil;
import com.feemanage.domain.BizProjectOutbound;
import com.feemanage.domain.BizProjectOutboundMain;
import com.feemanage.domain.vo.BizProjectOutboundMainVo;
import com.feemanage.domain.vo.ProjectOutboundMainVO;
import com.feemanage.domain.vo.ProjectOutboundVo;
import com.feemanage.mapper.bizProjectOutboundMainMapper;
import com.feemanage.mapper.bizProjectOutboundMapper;
import com.feemanage.service.IBizProjectOutboundMainService;
import com.feemanage.service.IBizProjectOutboundService;
import com.flowable.domain.vo.task.BpmTaskApproveReqVO;
import com.flowable.service.IFlowTaskService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service("biz_project_outbound_main")
public class BizProjectOutboundMainServiceImpl implements IBizProjectOutboundMainService {

    @Autowired
    private bizProjectOutboundMainMapper baseMapper;

    @Autowired
    private bizProjectOutboundMapper outboundMapper;

    @Autowired
    private IBizProjectOutboundService projectOutboundService;

    @Autowired
    private ApprovalApi approvalApi; //发起流程

    @Autowired
    private IFlowTaskService flowTaskService;//流程引擎

    private  final static  String modelName="经费外拨";
    /**
     * 查询列表
     * @param pageDomain
     * @param main
     * @return
     */
    @Override
    public IPage<BizProjectOutboundMainVo> selectList(PageDomain pageDomain, BizProjectOutboundMain main) {
        Page<BizProjectOutboundMainVo> page = new Page<>(pageDomain.getPageNum(), pageDomain.getPageSize());
        QueryWrapper<BizProjectOutboundMain> wrapper = getQuery(main);
        wrapper.groupBy("b.id ,b.project_id ,p.name,p.charger_name ,b.outbounddate ,bu.name,b.checkstatus,b.process_instance_id,b.checker ,b.checkdate");
        String orderByColumn = SqlUtil.escapeOrderBySql(pageDomain.getOrderByColumn());
        boolean isASC = SqlUtil.escapeOrderBySql(pageDomain.getIsAsc()).equalsIgnoreCase("asc");
        if (!StringUtils.isEmpty(orderByColumn))
        {
            wrapper.orderBy(true,isASC,orderByColumn);
        }
        IPage<BizProjectOutboundMainVo> list = baseMapper.selectPageList(page,wrapper);
        //获取当前用户所有的代办列表
        Map<String, String> instanceTaskMap = approvalApi.getInstanceTaskMap(modelName);

        for (BizProjectOutboundMainVo u : list.getRecords()) {
            // 判断是否是审核人，并设置taskId
            String processInstanceId = u.getProcessInstanceId();
            if (com.common.utils.StringUtils.isNotEmpty(processInstanceId) && instanceTaskMap.containsKey(processInstanceId)) {
                u.setTaskId(instanceTaskMap.get(processInstanceId));
                u.setIsAuditor(true);
            } else {
                u.setIsAuditor(false);
            }
        }
        return list;
    }

    /**
     * 统计检索
     * @param main
     * @return
     */
    @Override
    public List<HashMap<String, Integer>> selectListTotal(BizProjectOutboundMain main){
        QueryWrapper<BizProjectOutboundMain> wrapper = getQuery(main);
        return baseMapper.selectListTotal(wrapper);
    }

    /**
     * 检索条件拼接
     * @param main
     * @return
     */
    public QueryWrapper<BizProjectOutboundMain> getQuery(BizProjectOutboundMain main){
        Map<String, Object> params = main.getParams();
        QueryWrapper<BizProjectOutboundMain> wrapper = Wrappers.query();
        wrapper.eq(StringUtils.isNotBlank(main.getProjectId()),"b.project_id", main.getProjectId())
                .like(StringUtils.isNotBlank(main.getProjectName()), "p.name", main.getProjectName())
                .like(StringUtils.isNotBlank(main.getChargerName()),"p.charger_name",main.getChargerName())
                .between(ObjectUtils.isNotEmpty(params.get("beginTime")) && ObjectUtils.isNotEmpty(params.get("endTime")),
                        "b.outbounddate", params.get("beginTime"), params.get("endTime"))
                .ge(ObjectUtils.isNotEmpty(params.get("beginTime")) && ObjectUtils.isEmpty(params.get("endTime")),"b.outbounddate", params.get("beginTime"))
                .le(ObjectUtils.isEmpty(params.get("beginTime")) && ObjectUtils.isNotEmpty(params.get("endTime")),"b.outbounddate", params.get("endTime"))
                .eq(StringUtils.isNotBlank(main.getCheckstatus()),"b.checkstatus",main.getCheckstatus());

        if(StringUtils.isNotEmpty(main.getUnitId())){
            List<String> list = Arrays.stream(main.getUnitId().split(",")).collect(Collectors.toList());
            wrapper.in("p.unit_id",list);
        }

        //当前用户的角色
        String currentRoleKey = CurrentRoleUtils.getCurrentRoleKey();
        if (("biz_kyms").equals(currentRoleKey)) {//科研秘书 查看所属单位下的所有项目
            SysUser loginUser = SecurityUtils.getLoginUser().getUser();
            String units = loginUser.getUnitAdminScopeReal();
            if (StringUtils.isNotEmpty(units)) {
                List<String> unit = Arrays.stream(units.split(",")).collect(Collectors.toList());
                wrapper.in("p.unit_id",unit);
            }
        }
        return  wrapper;
    }

    /**
     * 获取基础信息
     * @param projectId
     * @return
     */
    @Override
    public ProjectOutboundMainVO getProOutFeeInfo(String projectId){
        ProjectOutboundMainVO vo = baseMapper.selectByProjectId(new QueryWrapper<BizProjectOutboundMain>().eq("p.ID",projectId));
        if(ObjectUtil.isNotNull(vo)){
            vo.setOutbounddate(LocalDate.now());
            List<ProjectOutboundVo> list = baseMapper.selectByProjectIdList(new QueryWrapper<BizProjectOutboundMain>().eq("p.PROJECT_ID",projectId));
           if (!list.isEmpty()){
               vo.setProjectOutboundList(list);
           }
        }
        return  vo;
    }

    /**
     * 编辑页面数据
     * @param Id
     * @return
     */
    @Override
    public ProjectOutboundMainVO getEditOutFeeInfo(String Id){
        ProjectOutboundMainVO vo = baseMapper.selectEditMain(new QueryWrapper<BizProjectOutboundMain>().eq("b.ID",Id));
        if (ObjectUtil.isNotNull(vo)){
            List<ProjectOutboundVo> list = baseMapper.selectEditList(new QueryWrapper<BizProjectOutboundMain>().eq("b.PROJECT_OUTBOUND_MAIN_ID",Id));
            if (!list.isEmpty()){
                vo.setProjectOutboundList(list);
            }
        }
        return  vo;
    }

    /**
     * 新增
     * @param mainVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String addProOutFee(ProjectOutboundMainVO mainVO) {
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        BizProjectOutboundMain main = new BizProjectOutboundMain();
        BeanUtils.copyProperties(mainVO,main);
        main.setOutbounddate(LocalDateTime.of(mainVO.getOutbounddate(),LocalTime.MIN));
        //暂存
        if(mainVO.getStatus().equalsIgnoreCase("-1")){
            main.setCheckstatus(mainVO.getStatus());
            main.setCheckdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            main.setChecker(loginUser.getNickName());
        }
        Boolean flag = baseMapper.insert(main)>0;
        if(flag){
            List<BizProjectOutbound> outbounds = new ArrayList<>();
            List<ProjectOutboundVo> list = mainVO.getProjectOutboundList();
            for (ProjectOutboundVo vo:list){
                BizProjectOutbound outbound = new BizProjectOutbound();
                BeanUtils.copyProperties(vo,outbound);
                outbound.setProjectId(main.getProjectId());
                outbound.setProjectOutboundMainId(main.getId());
                outbound.setOutboundDate(main.getOutbounddate());
                outbound.setCheckdate(main.getCheckdate());
                outbound.setCheckstatus(main.getCheckstatus());
                outbound.setChecker(main.getChecker());
                outbounds.add(outbound);
            }
            flag = projectOutboundService.saveBatch(outbounds);
        }
        String msg = flag ? null :"操作失败";
        //保存并通过
        if(mainVO.getStatus().equalsIgnoreCase("2")){
            updateBusinessStatus("local",main.getId(),main.getStatus(), loginUser.getNickName());
            updateTableStatus(main.getId(),main.getStatus(), loginUser.getNickName(),"0");
        }
        //提交
        if(mainVO.getStatus().equalsIgnoreCase("1")){
            String processInstanceId = approvalApi.businessEntryApproval(main.getId(), modelName);
            msg = StringUtils.isEmpty(processInstanceId)? BizProcessMessages.SAVE_PARTIAL_SUCCESS:null;
        }
        return msg;
    }

    /**
     * 编辑
     * @param mainVO
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String editProOutFee(ProjectOutboundMainVO mainVO) {
        SysUser loginUser = SecurityUtils.getLoginUser().getUser();
        BizProjectOutboundMain main = new BizProjectOutboundMain();
        BeanUtils.copyProperties(mainVO,main);
        if(mainVO.getOutbounddate() !=null){
            main.setOutbounddate(LocalDateTime.of(mainVO.getOutbounddate(),LocalTime.MIN));
        }
        //暂存
        if(main.getStatus().equalsIgnoreCase("-1")){
            //数据状态不为审核中,不更新数据状态
            if(!main.getCheckstatus().equalsIgnoreCase("1")) {
                main.setCheckstatus(main.getStatus());
                main.setCheckdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                main.setChecker(loginUser.getNickName());
            }
        }
        Boolean flag = baseMapper.updateById(main) >0;
        if(flag){
            List<BizProjectOutbound> outbounds = new ArrayList<>();
            List<ProjectOutboundVo> list = mainVO.getProjectOutboundList();
            for (ProjectOutboundVo vo:list){
                BizProjectOutbound outbound = new BizProjectOutbound();
                BeanUtils.copyProperties(vo,outbound);
                outbound.setOutboundDate(main.getOutbounddate());
                outbound.setCheckdate(main.getCheckdate());
                outbound.setCheckstatus(main.getCheckstatus());
                outbound.setChecker(main.getChecker());
                outbounds.add(outbound);
            }
            flag = projectOutboundService.updateBatchById(outbounds);
        }
        String msg = flag ? null :"操作失败";

        // 按钮状态为提交1:角色为科研人员，调流程引擎
        if(mainVO.getStatus().equalsIgnoreCase("1")){
            String returnProcessInstanceId = approvalApi.businessEntryApproval(main.getId(), modelName);
            msg = StringUtils.isEmpty(returnProcessInstanceId)?BizProcessMessages.SAVE_PARTIAL_SUCCESS:null;
        }

        //按钮状态为保存并通过2:角色为科研秘书/科研管理员
        if(mainVO.getStatus().equalsIgnoreCase("2")){
            //科研管理员的保存并通过，且数据状态为暂存-1或不通过3，直接更新状态
            if(mainVO.getCheckstatus().equalsIgnoreCase("-1") || mainVO.getCheckstatus().equalsIgnoreCase("3")){
                updateBusinessStatus("local",mainVO.getId(),mainVO.getStatus(),loginUser.getNickName());
                updateTableStatus(main.getId(),mainVO.getStatus(),loginUser.getNickName(),"0");
            }else{
                //此时当前审核人为该节点审核人，所以直接调流程引擎，通过该流程节点
                BpmTaskApproveReqVO bta = new BpmTaskApproveReqVO();
                bta.setId(mainVO.getTaskId());
                bta.setReason(SecurityUtils.getNickName() + "保存并通过");
                flowTaskService.approveTask(SecurityUtils.getUserId(), bta);
            }
        }

        return msg;
    }


    /**
     * 删除
     * @param ids
     * @param isValid
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean delProOutFee(Collection<String> ids, Boolean isValid){

        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        //先删从表，再删主表
        Boolean flag = outboundMapper.delete(new QueryWrapper<BizProjectOutbound>().in("project_outbound_main_id",ids))>0;
        Boolean flagMain = baseMapper.deleteBatchIds(ids) >0;

        return flag && flagMain;
    }

    /**
     * 更新审核状态id
     * @param businessId
     * @param checkStatus
     * @param sysUserId
     */
    private void updateTableStatus(String businessId, String checkStatus, String sysUserId,String processInstanceId){
        BizProjectOutboundMain main = new BizProjectOutboundMain();
        main.setId(businessId);
        main.setCheckstatus(checkStatus);
        main.setCheckdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        main.setChecker(sysUserId);
        if(StringUtils.isNotEmpty(processInstanceId)){
            main.setProcessInstanceId(processInstanceId);
        }
        baseMapper.updateById(main);
        updateStatus(businessId,checkStatus,sysUserId);//更新从表状态
    }

    /**
     * 更新从表状态
     * @param businessId
     * @param checkStatus
     * @param sysUserId
     */
    private void updateStatus(String businessId, String checkStatus, String sysUserId){
        BizProjectOutbound outbound = new BizProjectOutbound();
        outbound.setCheckstatus(checkStatus);
        outbound.setCheckdate(LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
        outbound.setChecker(sysUserId);
        outboundMapper.update(outbound,new UpdateWrapper<BizProjectOutbound>().eq("PROJECT_OUTBOUND_MAIN_ID",businessId));
    }

    @Override
    public void updateBusinessStatus(String tableName, String businessId, String checkStatus, String sysUserId) {
        if (StringUtils.isEmpty(tableName) || StringUtils.isEmpty(businessId) || StringUtils.isEmpty(checkStatus))
            return;
        //审核通过,反写BIZ_PROJECT_COOPERATION_UNIT
        if ("2".equals(checkStatus)) {
            List<ProjectOutboundVo> list = baseMapper.selectCheckList(new QueryWrapper<BizProjectOutboundMain>().eq("b.ID",businessId));
            for (ProjectOutboundVo vo:list){
                baseMapper.updateCooperationUnit(vo);
            }
        }
        if (!tableName.equalsIgnoreCase("local")){
            //更新从表
            updateStatus(businessId,checkStatus,sysUserId);
        }
    }
}
